
#include "stdafx.h"
#ifndef _NOSERVER_

#include "ServerSocket.h"
#include "ClientThread.h"
#include "Constant.h"

CServerSocket::CServerSocket(IServerSocketDelegate *delegate)
	:m_delegate(delegate)
{
}

CServerSocket::~CServerSocket()
{
}

LPVOID CServerSocket::initClientThread()
{
	CClientThread* pThread = (CClientThread*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_ClientNum*sizeof(CClientThread));
	if (pThread) for (intptr_t i = 0; i < m_ClientNum; i++) pThread[i].lock.SelfInit();
	return pThread;
}

void CServerSocket::doneClientThread()
{
	CClientThread *pThread = (CClientThread *)pClientThread; for (intptr_t i = 0; i < m_ClientNum; i++, pThread++)
	{
		pThread->lock.Lock();
		if (pThread->threadRunning())
			pThread->stop(StopThread_Reason::StopAll, true, true);
		else
			pThread->lock.Unlock();
		pThread->lock.SelfDone();
	}
}

typedef struct {
	CServerSocket *caller;
	CClientThread *pCltThread;
} st_StartClientThread;
DWORD WINAPI StartThread_Client(LPVOID p)
{
	CServerSocket *caller = ((st_StartClientThread*)p)->caller;
	CClientThread *pCltThread = ((st_StartClientThread*)p)->pCltThread;
	HeapFree(GetProcessHeap(), 0, p);
	return pCltThread->Thread_Client(caller->GetDelegate());
}
bool CServerSocket::startClientThread(SOCKET cltSock)
{
	TICK tk = TICK::Now(); bool threadStarted = false;
	if (pClientThread)
	{
		CClientThread *pCltThread = (CClientThread *)pClientThread;
		for (intptr_t i = 0; i < m_ClientNum; i++, pCltThread++) if (pCltThread->lock.TestLock())
		{
			if (!pCltThread->threadRunning())
			{
				pCltThread->init(cltSock, tk);
				st_StartClientThread *n = (st_StartClientThread*)HeapAlloc(GetProcessHeap(), 0, sizeof(st_StartClientThread));
				n->caller = this; n->pCltThread = pCltThread;
				pCltThread->startThread(CreateThread(NULL, 0, StartThread_Client, n, 0, NULL));
				threadStarted = true;
			}
			pCltThread->lock.Unlock();
			if (threadStarted) break;
		}
	}
	return threadStarted;
}

CClientThread *CServerSocket::GetClientThread(intptr_t idx)
{
	if (!pClientThread || idx < 0 || idx >= m_ClientNum) return nullptr;
	return ((CClientThread *)pClientThread) + idx;
}

#endif
